package com.ybt.communicate.core.manager;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.ybt.communicate.core.configration.IProtocolConfig;
import com.ybt.communicate.core.factory.IProtocolFactory;
import com.ybt.communicate.core.parser.IProtocolParser;
import com.ybt.configration.IYBTConfigration;
import com.ybt.configration.YBTConfigration;

public class ProtocolTypeManager {
    private static volatile ProtocolTypeManager factory;
    private static String CONFIG_DIR;
    private static String CONFIG_DIR_File;
    private static Logger logger = Logger.getLogger(ProtocolTypeManager.class);
    private Map<String, ProtocolMetadata> connectorMap;

    private ProtocolTypeManager() {
        CONFIG_DIR = YBTConfigration.getInstance().getProperty(
                IYBTConfigration.WORKFLOW_DEPLOY_PATH) + File.separator + "protocolType";
        CONFIG_DIR_File = CONFIG_DIR + File.separator + "protocolTypes.xml";
        connectorMap = new HashMap<String, ProtocolMetadata>();
        loadFromLocal();
    }

    public static ProtocolTypeManager getInstance() {
        if (factory == null) {
            synchronized(ProtocolTypeManager.class){
                if (factory == null) {
                    factory = new ProtocolTypeManager();
                }
            }
        }
        return factory;
    }

    /**
     * 根据协议类型获取协议解析器
     * @param type
     *            协议类型
     * @return 协议解析器
     * @throws ConnectorException
     */
    public IProtocolParser getProtocolParser(String type){
        ProtocolMetadata p = connectorMap.get(type);
        if(p==null){
            throw new RuntimeException("unsupport protocol type :" + type);
        }
        return p.parser;
    }


    public IProtocolFactory getProtocolFactory(String type){
        ProtocolMetadata p = connectorMap.get(type);
        if(p==null){
            throw new RuntimeException("unsupport protocol type :" + type);
        }
        return p.factory;
    }

    public  <E extends IProtocolConfig<E>>  E  createProtocolConfig(String type){
        ProtocolMetadata p = connectorMap.get(type);
        if(p==null){
            throw new RuntimeException("unsupport protocol type :" + type);
        }
        
        Class<IProtocolConfig> c = null;
        try {
            // 加载链接器类
            c = (Class<IProtocolConfig>) Class.forName(p.configClass);
            return (E) c.newInstance();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            throw new RuntimeException("load protocol configuration for " + p.configClass, e);
        }
    }

    private void loadFromLocal() {
        File dir = new File(CONFIG_DIR_File);
        Document doc = null;
        if (dir.exists()) {
            // 配置文件已经存在
            FileInputStream fi = null;
            try {
                fi = new FileInputStream(dir);
                SAXReader saxReader = new SAXReader();
                doc = saxReader.read(new InputStreamReader(fi, "utf8"));
            } catch (Exception e) {
                logger.error("loading " + CONFIG_DIR_File + " error ", e);
                return;
            } finally {
                if (fi != null) {
                    try {
                        fi.close();
                    } catch (Exception e) {
                        logger.error("closeing " + CONFIG_DIR_File + " error ",
                                e);
                    }
                }
            }
        } else {
            // 配置文件没存在
            doc = DocumentHelper.createDocument();
            doc.addElement("types");
        }
        
        List<Element> eles = doc.getRootElement().elements("type");
        if (eles == null)
            return;

        // 加载链接器
        for (Element conEle : eles) {
            String type = conEle.attributeValue("type");
            String configuration = conEle.elementTextTrim("configuration");
            String parser = conEle.elementTextTrim("parser");
            String factory = conEle.elementTextTrim("factory");

            ProtocolMetadata m = new ProtocolMetadata();
            m.type = String.valueOf(type);
            m.configClass = configuration;
            try {
                // 初始化协议解析器
                Class c =  Class.forName(parser);
                m.parser = (IProtocolParser) c.newInstance();
                
                // 初始化协议工厂
                c =  Class.forName(factory);
                m.factory = (IProtocolFactory) c.newInstance();
                
                this.connectorMap.put(m.type, m);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                logger.error("load protocol type for " + m.type, e);
            }

        }

    }

    class ProtocolMetadata{
        String type;
        String configClass;
        IProtocolParser parser;
        IProtocolFactory factory;
    }
    
    public static void main(String[] args) {
        ProtocolTypeManager.getInstance();
    }
}
